﻿using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
using OfficeOpenXml;
using UnityEditor;
using UnityEngine;
using XFGameFramework.ExcelSystem; 

namespace XFGameFramework.Localization
{

    [CustomEditor(typeof(MultiLanguageConfigs))]
    public class MultiLanguageConfigsInspector : Editor
    {

        private List<SerializedProperty> serializedProperties = null;

        private SerializedProperty m_Script = null;

        private void OnEnable()
        {
            serializedProperties = serializedObject.GetAllSerializedProperty();
            m_Script = serializedObject.FindProperty("m_Script");
        }


        public override void OnInspectorGUI()
        {

            serializedObject.Update();

            EditorGUI.BeginDisabledGroup(true);
            EditorGUILayout.PropertyField(m_Script);
            EditorGUI.EndDisabledGroup();

            foreach (var item in serializedProperties)
            {
                if (item.name == "excel_path") continue;

                EditorGUI.BeginDisabledGroup(item.name != "displayName"); 
                EditorGUILayout.PropertyField(item);
                EditorGUI.EndDisabledGroup();
            }
             
            if (GUILayout.Button("编辑多语言配表"))
            {
                OpenLocalizationConfigs(target as MultiLanguageConfigs);
            }

            serializedObject.ApplyModifiedProperties();

            OnGUIExcel();
        }

        public static void OpenLocalizationConfigs(MultiLanguageConfigs configs) 
        {
            if(configs == null) return;

            LocalizationConfigsWindow window = EditorWindow.GetWindow<LocalizationConfigsWindow>();
            window.Show();
          
            window.SetCurrentConfigs(configs);
        }


        private GUIContent excel_path_content;

        private void OnGUIExcel()
        {
            MultiLanguageConfigs multiLanguageConfigs = target as MultiLanguageConfigs;
            if (multiLanguageConfigs == null)
                return;

            GUILayout.Space(10);

            if (!string.IsNullOrEmpty(multiLanguageConfigs.excel_path))
            {
                if (!File.Exists(multiLanguageConfigs.excel_path))
                { 
                    multiLanguageConfigs.excel_path = string.Empty;
                    EditorUtility.SetDirty(multiLanguageConfigs);
                }

                EditorGUILayout.LabelField(string.Empty, "Excel路径", "BoldLabel");

                if (excel_path_content == null)
                    excel_path_content = new GUIContent();

                excel_path_content.text = multiLanguageConfigs.excel_path;
                excel_path_content.tooltip = multiLanguageConfigs.excel_path;

                EditorGUILayout.LabelField(excel_path_content);

                GUILayout.BeginHorizontal();

                GUILayout.FlexibleSpace();

                if (GUILayout.Button("更换Excel"))
                {
                    EditorApplication.delayCall += () => 
                    {  
                        // 选择
                        string excel_path = EditorUtility.OpenFilePanel("请选择Excel文件", string.Format("{0}/../", Application.dataPath), "xlsx");
                        if (!string.IsNullOrEmpty(excel_path))
                        {
                            multiLanguageConfigs.excel_path = excel_path;
                            EditorUtility.SetDirty(multiLanguageConfigs);
                        }
                    };

                }
                if (GUILayout.Button("在文件夹中打开"))
                {
                    EditorApplication.delayCall += () => 
                    {  
                        EditorUtility.RevealInFinder(multiLanguageConfigs.excel_path);
                    };
                }

                GUILayout.EndHorizontal();
            }

            //EditorWindow.focusedWindow

            GUILayout.BeginHorizontal();

            if (GUILayout.Button("导入Excel"))
            {
                EditorApplication.delayCall += ()=> ImportExcel(multiLanguageConfigs);
            }
            if (GUILayout.Button("导出Excel"))
            {
                EditorApplication.delayCall += () => ExportExcel(multiLanguageConfigs);
            }

            GUILayout.EndHorizontal();

        }


        private void ExportExcel(MultiLanguageConfigs multiLanguageConfigs)
        { 

            if (string.IsNullOrEmpty(multiLanguageConfigs.excel_path))
            { 
                // 选择
                string excel_path = EditorUtility.OpenFolderPanel("请选择Excel存放目录", string.Format("{0}/../", Application.dataPath), string.Empty);
                if (string.IsNullOrEmpty(excel_path))
                    return;

                string fileName = multiLanguageConfigs.name;

                if (!string.IsNullOrEmpty(multiLanguageConfigs.displayName))
                    fileName = string.Format("{0}({1})", fileName, multiLanguageConfigs.displayName);

                multiLanguageConfigs.excel_path = string.Format("{0}/{1}.xlsx", excel_path, fileName);
                EditorUtility.SetDirty(multiLanguageConfigs);
            }
             
            using ExcelPackage excel = new ExcelPackage(new FileInfo(multiLanguageConfigs.excel_path));
             
            List<string> sheetNames = new List<string>();

            foreach (var item in excel.Workbook.Worksheets)
            {
                sheetNames.Add(item.Name);
            }

            // 清空excel
            foreach (var item in sheetNames)
            {
                excel.Workbook.Worksheets.Delete(item);
            }
             
            foreach (var item in multiLanguageConfigs.Languages)
            {
                string language = item.language.ToString();
                if (!string.IsNullOrEmpty(item.displayName))
                    language = string.Format("{0}({1})",language,item.displayName);

                ExcelWorksheet sheet = excel.Workbook.Worksheets.Add(language);

                sheet.SetValue(1, 1, "id");
                sheet.SetValue(2, 1, "int");
                sheet.SetValue(3, 1, "唯一标识");

                sheet.SetValue(1, 2, "type");
                sheet.SetValue(2, 2, "string");
                sheet.SetValue(3, 2, "配置类型");

                sheet.SetValue(1, 3, "str");
                sheet.SetValue(2, 3, "string");
                sheet.SetValue(3, 3, "string类型值");

                sheet.SetValue(1, 4, "image");
                sheet.SetValue(2, 4, "string");
                sheet.SetValue(3, 4, "图片类型值");

                sheet.SetValue(1, 5, "url");
                sheet.SetValue(2, 5, "string");
                sheet.SetValue(3, 5, "网络图片地址");

                sheet.SetValue(1, 6, "notes");
                sheet.SetValue(2, 6, "string");
                sheet.SetValue(3, 6, "备注");

                int index = 3;

                foreach (var languageInfo in item.languagesInfo)
                {
                    index++; 

                    sheet.SetValue(index, 1, languageInfo.id); 
                    sheet.SetValue(index, 2, languageInfo.type.ToString()); 
                    sheet.SetValue(index, 3, languageInfo.str); 
                    sheet.SetValue(index, 4, JsonConvert.SerializeObject(languageInfo.image, Formatting.Indented)); 
                    sheet.SetValue(index, 5, languageInfo.url); 
                    sheet.SetValue(index, 6, languageInfo.notes); 
                }

            }

            try
            {
                excel.Save();
                EditorWindow.focusedWindow.ShowNotification(new GUIContent("导出成功!"));
            }
            catch (System.Exception e)
            {
                Debug.LogError(e.ToString());
                EditorWindow.focusedWindow.ShowNotification(new GUIContent("导出失败,请检查excel文件是否被其他应用使用中!"));
            } 

        }

        
        private void ImportExcel(MultiLanguageConfigs multiLanguageConfigs)
        { 

            if (string.IsNullOrEmpty(multiLanguageConfigs.excel_path))
            {
                string excel_path = EditorUtility.OpenFilePanel("请选择Excel文件", string.Format("{0}/../", Application.dataPath), "xlsx");
                if (string.IsNullOrEmpty(excel_path))
                    return;
                multiLanguageConfigs.excel_path = excel_path;
                EditorUtility.SetDirty(multiLanguageConfigs); 
            }

            using ExcelPackage excel = new ExcelPackage(new FileInfo(multiLanguageConfigs.excel_path));

            multiLanguageConfigs.displayName = GetDisplayName( Path.GetFileNameWithoutExtension(multiLanguageConfigs.excel_path));

            List<SystemLanguage> languages = new List<SystemLanguage>();
             
            foreach (var sheet in excel.Workbook.Worksheets)
            {
                SystemLanguage language = ParseLanguage(sheet.Name);

                languages.Add(language);
                  
                LanguageConfig languageConfig = multiLanguageConfigs.GetLanguageConfigData(language);
                if (languageConfig == null) 
                {
                    languageConfig = CreateInstance<LanguageConfig>();
                    languageConfig.language = language;
                    string asset_path = AssetDatabase.GetAssetPath(multiLanguageConfigs);
                    string path = string.Format("Assets/Extensions/Localization/{0}/{1}.asset", AssetDatabase.AssetPathToGUID(asset_path),language);

                    if (!Directory.Exists(Path.GetDirectoryName(path))) 
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(path));
                    }

                    AssetDatabase.CreateAsset(languageConfig, path);
                    AssetDatabase.SaveAssets();
                    AssetDatabase.Refresh();
                }

                languageConfig.languagesInfo.Clear();

                int row = ExcelManager.GetExcelRow(sheet);

                for (int i = 4; i <= row; i++)
                { 
                    LanguageInfo languageInfo = new LanguageInfo();

                    object idObj = sheet.GetValue(i, 1);

                    if(idObj != null)
                        int.TryParse(idObj.ToString(), out languageInfo.id);

                    object typeObj = sheet.GetValue(i, 2);

                    if (typeObj != null) 
                        Enum.TryParse( typeObj.ToString(),out languageInfo.type);
                    

                    object strObj = sheet.GetValue(i, 3);

                    if(strObj != null)
                        languageInfo.str = strObj.ToString();

                    object imageObj = sheet.GetValue(i, 4);
                    if (imageObj != null) 
                    {
                        try
                        {
                            languageInfo.image = JsonConvert.DeserializeObject<ImageInfo>(imageObj.ToString());
                        }
                        catch (Exception e)
                        {
                            Debug.LogErrorFormat("解析ImageInfo失败:{0}", e.ToString());
                        }
                    }

                    object urlObj = sheet.GetValue(i, 5);
                    if(urlObj != null)
                        languageInfo.url = urlObj.ToString();

                    object notesObj = sheet.GetValue(i, 6);
                    if(notesObj != null)
                        languageInfo.notes = notesObj.ToString();

                    languageConfig.languagesInfo.Add(languageInfo);
                }

                languageConfig.displayName = GetDisplayName(sheet.Name);
                languageConfig.Save();
            }


            for (int i = multiLanguageConfigs.Languages.Count - 1; i >= 0; i--)
            {
                LanguageConfig languageConfig = multiLanguageConfigs.Languages[i];

                if (languages.Contains(languageConfig.language))
                    continue;

                AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath( languageConfig));
                multiLanguageConfigs.Languages.RemoveAt(i);
            }
           
            EditorUtility.SetDirty(multiLanguageConfigs); 
            AssetDatabase.SaveAssets();
        }

        private SystemLanguage ParseLanguage(string name) 
        {
            string n = name;

            if (n.Contains("(") && n.Contains(")"))
            {
                for (int i = 0; i < n.Length; i++) 
                {
                    if (n[i] == '(') 
                    { 
                        n = n.Substring(0,i);
                        break;
                    }
                }
            }

            object obj = Enum.Parse(typeof(SystemLanguage), n); 
            return (SystemLanguage)obj;
        }

        private string GetDisplayName(string name) 
        {
            if (name.EndsWith(")") && name.Contains("(")) 
            {
                for (int i = name.Length - 1; i >= 0; i--)
                {
                    if (name[i] == '(') 
                    { 
                        return name.Substring(i + 1,name.Length - i -2);
                    }
                }
            }

            return string.Empty;
        }

    }
}

